home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / libpr3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  9.9 KB  |  368 lines  |  [TEXT/R*ch]

  1. /*
  2.  * libpr3.c - a library of primitive object output routines, part 3 of 3.
  3.  *
  4.  * Author:  Eric Haines, 3D/Eye, Inc.
  5.  *
  6.  */
  7.  
  8. /*-----------------------------------------------------------------*/
  9. /* include section */
  10. /*-----------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16.  
  17. #include "lib.h"
  18. #include "drv.h"
  19.  
  20.  
  21. /*-----------------------------------------------------------------*/
  22. /* defines/constants section */
  23. /*-----------------------------------------------------------------*/
  24.  
  25.  
  26. static unsigned int hfcount = 0;
  27.  
  28. /*-----------------------------------------------------------------*/
  29. static char *
  30. create_height_file(filename, height, width, data, type)
  31.     char *filename;
  32.     unsigned int height, width;
  33.     float **data;
  34.     int type;
  35. {
  36.     FILE *file;
  37.     float v;
  38.     unsigned int i, j;
  39.     unsigned char r, g, b;
  40.     unsigned char tgaheader[18];
  41.  
  42.     if (filename == NULL) {
  43.     /* Need to create a new name for the height file */
  44.     filename = malloc(10 * sizeof(char));
  45.     if (filename == NULL) return NULL;
  46.     sprintf(filename, "hf%03d.tga", hfcount++);
  47.     }
  48.     if ((file = fopen(filename, "wb")) == NULL) return NULL;
  49.     if (type == 0) {
  50.     /* Targa style height field for POV-Ray or Polyray */
  51.     memset(tgaheader, 0, 18);
  52.     tgaheader[2] = 2;
  53.     tgaheader[12] = (unsigned char)(width & 0xFF);
  54.     tgaheader[13] = (unsigned char)((width >> 8) & 0xFF);
  55.     tgaheader[14] = (unsigned char)(height & 0xFF);
  56.     tgaheader[15] = (unsigned char)((height >> 8) & 0xFF);
  57.     tgaheader[16] = 24;
  58.     tgaheader[17] = 0x20;
  59.     fwrite(tgaheader, 18, 1, file);
  60.     for (i=0;i<height;i++) {
  61.         PLATFORM_MULTITASK();
  62.         for (j=0;j<width;j++) {
  63.         v = data[i][j];
  64.         if (v < -128.0) v = -128.0;
  65.         if (v > 127.0) v = 127.0;
  66.         v += 128.0;
  67.         r = v;
  68.         v -= (float)r;
  69.         g = (unsigned char)(256.0 * v);
  70.         b = 0;
  71.         fputc(b, file);
  72.         fputc(g, file);
  73.         fputc(r, file);
  74.         }
  75.     }
  76.     } else {
  77.     /* Only square height fields in RayShade */
  78.     if (height < width) width = height;
  79.     else if (width < height) height = width;
  80.  
  81.     /* Start by storing the size as an int */
  82.     fwrite(&height, sizeof(int), 1, file);
  83.  
  84.     /* Now store height values as native floats */
  85.     for (i=0;i<height;i++)
  86.         for (j=0;j<width;j++)
  87.         fwrite(&data[i][j], sizeof(float), 1, file);
  88.     }
  89.     fclose(file);
  90.  
  91.     return filename;
  92. }
  93.  
  94.  
  95. /*-----------------------------------------------------------------*/
  96. void
  97. lib_output_height(filename, data, height, width, x0, x1, y0, y1, z0, z1)
  98.     char *filename;
  99.     float **data;
  100.     unsigned int height, width;
  101.     double x0, x1;
  102.     double y0, y1;
  103.     double z0, z1;
  104. {
  105.     object_ptr new_object;
  106.  
  107.     if (gRT_out_format == OUTPUT_DELAYED) {
  108.     filename = create_height_file(filename, height, width, data, 0);
  109.     if (filename == NULL) return;
  110.  
  111.     /* Save all the pertinent information */
  112.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  113.     if (new_object == NULL)
  114.         /* Quietly fail */
  115.         return;
  116.     new_object->object_type  = HEIGHT_OBJ;
  117.     new_object->curve_format = OUTPUT_CURVES;
  118.     new_object->surf_index   = gTexture_count;
  119.     new_object->object_data.height.width = width;
  120.     new_object->object_data.height.height = height;
  121.     new_object->object_data.height.data = data;
  122.     new_object->object_data.height.filename = filename;
  123.     new_object->object_data.height.x0 = x0;
  124.     new_object->object_data.height.x1 = x1;
  125.     new_object->object_data.height.y0 = y0;
  126.     new_object->object_data.height.y1 = y1;
  127.     new_object->object_data.height.z0 = z0;
  128.     new_object->object_data.height.z1 = z1;
  129.     new_object->next_object = gLib_objects;
  130.     gLib_objects = new_object;
  131.     } else {
  132.     switch (gRT_out_format) {
  133.         case OUTPUT_VIDEO:
  134.         case OUTPUT_NFF:
  135.         case OUTPUT_PLG:
  136.         case OUTPUT_OBJ:
  137.         case OUTPUT_QRT:
  138.         case OUTPUT_RTRACE:
  139.         case OUTPUT_VIVID:
  140.         case OUTPUT_RAWTRI:
  141.         case OUTPUT_RIB:
  142.         case OUTPUT_DXF:
  143.         lib_output_polygon_height(height, width, data,
  144.                       x0, x1, y0, y1, z0, z1);
  145.         break;
  146.         case OUTPUT_POVRAY_10:
  147.         case OUTPUT_POVRAY_20:
  148.         filename = create_height_file(filename, height, width, data, 0);
  149.         if (filename == NULL) return;
  150.  
  151.         tab_indent();
  152.         fprintf(gOutfile, "object {\n");
  153.         tab_inc();
  154.  
  155.         tab_indent();
  156.         fprintf(gOutfile, "height_field { tga \"%s\" }", filename);
  157.         if (gRT_out_format == OUTPUT_POVRAY_10) {
  158.             tab_indent();
  159.             fprintf(gOutfile, "scale <%g %g %g>\n",
  160.                 fabs(x1 - x0), fabs(y1 - y0), fabs(z1 - z0));
  161.             tab_indent();
  162.             fprintf(gOutfile, "translate <%g %g %g>\n", x0, y0, z0);
  163.         } else {
  164.             tab_indent();
  165.             fprintf(gOutfile, "scale <%g, %g, %g>\n",
  166.                 fabs(x1 - x0), fabs(y1 - y0), fabs(z1 - z0));
  167.             tab_indent();
  168.             fprintf(gOutfile, "translate <%g, %g, %g>\n", x0, y0, z0);
  169.         }
  170.  
  171.         if (gTexture_name != NULL) {
  172.             tab_indent();
  173.             fprintf(gOutfile, "texture { %s }", gTexture_name);
  174.         }
  175.  
  176.         tab_dec();
  177.         tab_indent();
  178.         fprintf(gOutfile, "} // object - Height Field\n");
  179.         fprintf(gOutfile, "\n");
  180.         break;
  181.  
  182.         case OUTPUT_POLYRAY:
  183.         filename = create_height_file(filename, height, width, data, 0);
  184.         if (filename == NULL) return;
  185.         tab_indent();
  186.         fprintf(gOutfile, "object { height_field \"%s\" ", filename);
  187.         fprintf(gOutfile, "scale <%g, 1, %g> ",
  188.             fabs(x1-x0), fabs(z1-z0));
  189.         fprintf(gOutfile, "translate <%g, %g, %g> ", x0, y0, z0);
  190.         if (gTexture_name != NULL)
  191.             fprintf(gOutfile, " %s", gTexture_name);
  192.         fprintf(gOutfile, " }\n");
  193.         fprintf(gOutfile, "\n");
  194.         break;
  195.  
  196.         case OUTPUT_RAYSHADE:
  197.         filename = create_height_file(filename, height, width, data, 1);
  198.         if (filename == NULL) return;
  199.         fprintf(gOutfile, "heightfield ");
  200.         if (gTexture_name != NULL)
  201.             fprintf(gOutfile, " %s", gTexture_name);
  202.         fprintf(gOutfile, "\"%s\" ", filename);
  203.         fprintf(gOutfile, "rotate 1 0 0 90 ");
  204.         fprintf(gOutfile, "scale  %g 1 %g ",
  205.             fabs(x1 - x0), fabs(z1 - z0));
  206.         fprintf(gOutfile, "translate  %g %g %g ", x0, y0, z0);
  207.         fprintf(gOutfile, "\n");
  208.         break;
  209.  
  210.         case OUTPUT_ART:
  211.         filename = create_height_file(filename, height, width, data, 1);
  212.         if (filename == NULL) return;
  213.  
  214.         tab_indent();
  215.         fprintf(gOutfile, "geometry {\n");
  216.         tab_inc();
  217.  
  218.         tab_indent();
  219.         fprintf(gOutfile, "translate(%g, %g, %g)\n", x0, y0, z0);
  220.         tab_indent();
  221.         fprintf(gOutfile, "scale(%g, 1, %g)\n",
  222.             fabs(x1 - x0), fabs(z1 - z0));
  223.         tab_indent();
  224.         fprintf(gOutfile, "rotate(-90, x)\n");
  225.         tab_indent();
  226.         fprintf(gOutfile, "heightfield \"%s\"\n ", filename);
  227.  
  228.         tab_dec();
  229.         tab_indent();
  230.         fprintf(gOutfile, "}\n");
  231.         fprintf(gOutfile, "\n");
  232.         break;
  233.     }
  234.     }
  235. }
  236.  
  237.  
  238. /*-----------------------------------------------------------------*/
  239. void
  240. lib_output_torus(center, normal, iradius, oradius, curve_format)
  241.     COORD3 center, normal;
  242.     double iradius, oradius;
  243.     int curve_format;
  244. {
  245.     object_ptr new_object;
  246.     double len, xang, zang;
  247.  
  248.     if (gRT_out_format == OUTPUT_DELAYED) {
  249.     /* Save all the pertinent information */
  250.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  251.     if (new_object == NULL)
  252.         /* Quietly fail */
  253.         return;
  254.     new_object->object_type  = TORUS_OBJ;
  255.     new_object->curve_format = curve_format;
  256.     new_object->surf_index   = gTexture_count;
  257.     COPY_COORD3(new_object->object_data.torus.center, center);
  258.     COPY_COORD3(new_object->object_data.torus.normal, normal);
  259.     new_object->object_data.torus.iradius = iradius;
  260.     new_object->object_data.torus.oradius = oradius;
  261.     new_object->next_object = gLib_objects;
  262.     gLib_objects = new_object;
  263.     } else if (curve_format == OUTPUT_CURVES) {
  264.     switch (gRT_out_format) {
  265.         case OUTPUT_VIDEO:
  266.         case OUTPUT_NFF:
  267.         case OUTPUT_VIVID:
  268.         case OUTPUT_QRT:
  269.         case OUTPUT_POVRAY_10:
  270.         case OUTPUT_PLG:
  271.         case OUTPUT_OBJ:
  272.         case OUTPUT_RTRACE:
  273.         case OUTPUT_RAWTRI:
  274.         case OUTPUT_DXF:
  275.         lib_output_polygon_torus(center, normal, iradius, oradius);
  276.         break;
  277.         case OUTPUT_POVRAY_20:
  278.         /*
  279.          A torus object lies in the x-z plane.  We need to determine
  280.          the angles of rotation to get it lined up with "normal".
  281.          */
  282.         tab_indent();
  283.         fprintf(gOutfile, "torus {\n");
  284.         tab_inc();
  285.  
  286.         tab_indent();
  287.         fprintf(gOutfile, "%g, %g\n", iradius, oradius);
  288.  
  289.         (void)lib_normalize_vector(normal);
  290.         len = sqrt(normal[X] * normal[X] + normal[Y] * normal[Y]);
  291.         xang = 180.0 * asin(normal[Z]) / PI;
  292.         if (len < EPSILON)
  293.             zang = 0.0;
  294.         else
  295.             zang = -180.0 * acos(normal[Y] / len) / PI;
  296.         if (normal[X] < 0)
  297.             zang = -zang;
  298.  
  299.         if (ABSOLUTE(xang) > EPSILON || ABSOLUTE(zang) > EPSILON) {
  300.             tab_indent();
  301.             fprintf(gOutfile, "rotate <%g, 0, %g>\n", xang, zang);
  302.         }
  303.  
  304.         if (ABSOLUTE(center[X]) > EPSILON ||
  305.             ABSOLUTE(center[Y]) > EPSILON ||
  306.             ABSOLUTE(center[Z]) > EPSILON) {
  307.             tab_indent();
  308.             fprintf(gOutfile, "translate <%g, %g, %g>\n",
  309.                 center[X], center[Y], center[Z]);
  310.         }
  311.  
  312.         if (gTexture_name != NULL) {
  313.             tab_indent();
  314.             fprintf(gOutfile, "texture { %s }", gTexture_name);
  315.         }
  316.         fprintf(gOutfile, "\n");
  317.  
  318.         tab_dec();
  319.         tab_indent();
  320.         fprintf(gOutfile, "} // torus\n");
  321.         fprintf(gOutfile, "\n");
  322.         break;
  323.  
  324.         case OUTPUT_POLYRAY:
  325.         tab_indent();
  326.         fprintf(gOutfile, "object { torus %g, %g", iradius, oradius);
  327.         fprintf(gOutfile, ", <%g, %g, %g>, <%g, %g, %g>",
  328.             center[X], center[Y], center[Z],
  329.             normal[X], normal[Y], normal[Z]);
  330.         if (gTexture_name != NULL)
  331.             fprintf(gOutfile, " %s", gTexture_name);
  332.         fprintf(gOutfile, " }\n");
  333.         fprintf(gOutfile, "\n");
  334.         break;
  335.  
  336.         case OUTPUT_RAYSHADE:
  337.         fprintf(gOutfile, "torus ");
  338.         if (gTexture_name != NULL)
  339.             fprintf(gOutfile, "%s ", gTexture_name);
  340.         fprintf(gOutfile, " %g %g %g %g %g %g %g %g\n",
  341.             iradius, oradius,
  342.             center[X], center[Y], center[Z],
  343.             normal[X], normal[Y], normal[Z]);
  344.         break;
  345.  
  346.         case OUTPUT_ART:
  347.         tab_indent();
  348.         fprintf(gOutfile, "torus {\n");
  349.         tab_inc();
  350.  
  351.         tab_indent();
  352.         fprintf(gOutfile,
  353.         "radius %g  center(%g, %g, %g)  radius %g  center(%g, %g, %g)\n",
  354.               iradius, oradius,
  355.               center[X], center[Y], center[Z],
  356.               normal[X], normal[Y], normal[Z]);
  357.         tab_dec();
  358.         tab_indent();
  359.         fprintf(gOutfile, "}\n");
  360.         fprintf(gOutfile, "\n");
  361.         break;
  362.     }
  363.     } else {
  364.     lib_output_polygon_torus(center, normal, iradius, oradius);
  365.     }
  366. }
  367.  
  368.